import hashlib

from sqlalchemy import Select
from sqlmodel import SQLModel, Field, Session, select

from settings import engine, auto_session


class User(SQLModel, table=True):
    """
    id:账号
    name:用户名
    email:用户邮箱
    privilegelevel:用户权限等级，0为普通用户，1为管理员级别，2为超级管理员，权限高的才可以修改权限低的用户的权限
    password_sha256:用户密码的sha256散列值
    """
    __tablename__ = 'userinfo'
    id: int = Field(primary_key=True, default=None)
    name: str = Field(unique=True)
    email: str = Field(unique=True)
    privilegelevel: int = Field(default=0)
    password_sha256: str
    failed_attempts: int = Field(default=0)
    islocked: bool = Field(default=False)

    def __init__(self,name:str = '', email:str = '', privilegelevel:int = 0, password:str='', failed_attempts:int = 0, islocked:bool = False,**kwargs):
        kwargs['password_sha256'] = hashlib.sha256(password.encode()).hexdigest()
        kwargs['name'] = name
        kwargs['email'] = email
        kwargs['privilegelevel'] = privilegelevel
        kwargs['failed_attempts'] = failed_attempts
        kwargs['islocked'] = islocked
        super().__init__(**kwargs)
    def to_dict(self):
        return self.model_dump()


# SQLModel.metadata.create_all(engine)



@auto_session
def search_user_by_id(id: int, session: Session = None) -> bool | None:
    """
    根据用户ID查询用户是否存在。

    参数:
        id (int): 用户ID。

    返回:
        bool | None: 如果用户存在返回True，否则返回False；如果发生错误返回None。
    """
    statement: Select = select(User).where(User.id == id)  # 明确使用 Select 类型
    result = session.exec(statement)  # 直接执行查询
    if result.first() is not None:
        return True
    else:
        return False

@auto_session
def search_user_by_email(email: str,  session: Session = None) -> int | None:
    """
    根据用户邮箱查询用户是否存在。

    参数:
        email (str): 用户邮箱。

    返回:
        int | None: 如果用户存在返回id，否则返回-1；如果发生错误返回None。
    """
    statement: Select = select(User.id).where(User.email == email)  # 明确使用 Select 类型
    result = session.exec(statement).first()  # 直接执行查询
    if result is not None:
        return result
    else:
        return -1

@auto_session
def search_user_by_name(name: str, session: Session = None) -> int | None:
    """
    根据用户邮箱查询用户是否存在。

    参数:
        name (str): 用户名。

    返回:
        int | None: 如果用户存在返回id，否则返回-1；如果发生错误返回None。
    """
    statement: Select = select(User.id).where(User.name == name)  # 明确使用 Select 类型
    result = session.exec(statement).first()  # 直接执行查询
    if result is not None:
        return result
    else:
        return -1

@auto_session
def register(user: User, session: Session = None) -> int | None:
    """
    注册新用户。

    参数:
        user (User): 包含用户信息的User对象。

    返回:
        int | None: 注册成功返回用户ID，名字已存在返回-1，邮箱已注册返回-2，发生错误返回None。
    """
    if search_user_by_name(name = user.name,session = session) > 0:
        return -1
    if search_user_by_email(email = user.email,session=session) > 0:
        return -2
    
    session.add(user)
    session.flush()  # 立即执行插入操作以生成id
    session.refresh(user)  # 刷新对象以获取数据库生成的id
    
    return user.id

@auto_session
def change_password(id: int, newpassword_sha256: str, session: Session = None) -> bool | None:
    """
    修改用户密码。

    参数:
        id (int): 用户ID。
        newpassword_sha256 (str): 新密码的SHA256哈希值。

    返回:
        bool | None: 如果密码修改成功返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return False

    user.password_sha256 = newpassword_sha256
    session.flush()  # 立即同步到数据库但不提交
    return True

def get_userinfo_key_list() -> list[str] | None:
    """
    获取用户信息表的用户可以访问的字段列表。

    返回:
        list[str] | None: 包含用户信息表字段名称的列表；如果发生错误返回None。
    """
    return User.model_fields.keys() - ['password_sha256']

@auto_session
def get_userinfo(id: int, infolist: list[str], session: Session = None) -> dict | None:
    """
    根据用户ID和指定字段列表获取用户信息（SQLModel版本）。

    参数:
        id (int): 用户ID。
        infolist (list[str]): 需要获取的字段名称列表。

    返回:
        dict | None: 包含指定字段信息的字典；如果用户不存在返回空字典；如果发生错误返回None。
    """
    # 构造动态查询字段
    fields = [getattr(User, field) for field in infolist]
    # 构建查询语句
    statement:Select = select(*fields).where(User.id == id)

    # 执行查询
    result = session.exec(statement).all()

    if result:
        return dict(zip(infolist, result))
    return {}

@auto_session  # 添加自动会话管理装饰器
def verify_id_and_email(id: int, email: str, session: Session = None) -> int | None:
    """
    验证用户ID和邮箱是否匹配（SQLModel版本）。

    参数:
        id (int): 用户ID。
        email (str): 用户邮箱。

    返回:
        int | None: 0表示验证成功，1表示用户不存在，2表示邮箱不匹配；如果发生错误返回None。
    """
    # 使用SQLModel ORM查询替代原生SQL
    statement:Select = select(User.email).where(User.id == id)
    result = session.exec(statement).first()

    if result is None:
        return 1
    elif result == email:
        return 0
    else:
        return 2

@auto_session  # 新增装饰器实现自动会话管理
def verify_id_and_password(id: int, password_sha256: str, session: Session = None) -> int | None:
    """
    验证用户ID和密码是否匹配（SQLModel版本）。

    参数:
        id (int): 用户ID。
        password_sha256 (str): 密码的SHA256哈希值。

    返回:
        int | None: 0表示验证成功，1表示用户不存在，2表示密码不匹配；如果发生错误返回None。
    """

    # 使用SQLModel ORM查询替代原生SQL
    user = session.get(User, id)

    if user is None:
        return 1
    elif user.password_sha256 == password_sha256:
        return 0
    else:
        return 2

@auto_session
def set_user_privilege(id: int, privilegelevel: int, session: Session = None) -> bool | None:
    """
    设置用户的权限级别。

    参数:
        id (int): 用户ID。
        privilegelevel (int): 权限级别。

    返回:
        bool | None: 如果权限设置成功返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return False

    user.privilegelevel =privilegelevel
    session.flush()
    return True

@auto_session
def get_user_privilege(id: int, session: Session = None) -> int | None:
    """
    获取用户的权限级别。

    参数:
        id (int): 用户ID。

    返回:
        int | None: 用户的权限级别；如果用户不存在返回None；如果发生错误返回None。
    """
    try:
        user = session.get(User, id)
    except Exception as e:
        print(e)
        return None
    if not user:
        return None

    return user.privilegelevel



    ##############################################################
@auto_session
def get_all_userinfo(session: Session = None) -> list[dict] | None:
    """
    获取所有用户的所有字段信息。

    参数:
        session (Session): 数据库会话对象。

    返回:
        list[dict] | None: 包含所有用户信息的字典列表；如果发生错误返回None。
    """
    # 获取 User 表的所有字段
    fields = [getattr(User, column.name) for column in User.__table__.columns]

    # 构建查询语句，查询所有字段
    statement = select(*fields)

    try:
        # 执行查询，获取所有用户数据
        result = session.exec(statement).all()

        # 将查询结果转换为字典列表
        return [dict(zip([column.name for column in User.__table__.columns], user)) for user in result]

    except Exception as e:
        print(f"Error: {e}")
        return None


@auto_session
def get_userinfo_by_id(user_id: int, session: Session = None) -> dict | None:
    """
    根据用户 ID 获取该用户的所有字段信息。

    参数:
        user_id (int): 要查询的用户 ID。
        session (Session): 数据库会话对象。

    返回:
        dict | None: 包含该用户信息的字典；如果发生错误或未找到用户返回 None。
    """
    # 获取 User 表的所有字段
    fields = [getattr(User, column.name) for column in User.__table__.columns]

    # 构建查询语句，查询特定用户
    statement = select(*fields).where(User.id == user_id)

    try:
        # 执行查询，获取指定用户的数据
        result = session.exec(statement).one_or_none()

        # 如果查询结果为空，说明用户不存在
        if result is None:
            return None

        # 将查询结果转换为字典并返回
        return dict(zip([column.name for column in User.__table__.columns], result))

    except Exception as e:
        print(f"Error: {e}")
        return None


@auto_session
def lock_user(id: int, session: Session = None) -> bool | None:
    """
    锁定用户。

    参数:
        id (int): 用户ID。

    返回:
        bool | None: 如果锁定成功返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return False

    user.islocked = True
    session.flush()
    return True

@auto_session
def unlock_user(id: int, session: Session = None) -> bool | None:
    """
    解锁用户。

    参数:
        id (int): 用户ID。

    返回:
        bool | None: 如果解锁成功返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return False

    user.islocked = False
    session.flush()
    return True

@auto_session
def user_islocked(id: int, session: Session = None) ->  bool | None:
    """
    判断用户是否被锁定。

    参数:
        id (int): 用户ID。

    返回:
        bool | None: 如果用户被锁定返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return None
    return user.islocked

@auto_session
def get_user_failed_attempts(id: int, session: Session = None) -> int | None:
    """
    获取用户失败登录次数。

    参数:
        id (int): 用户ID。

    返回:
        int | None: 用户失败登录次数；如果用户不存在返回None；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return None
    return user.failed_attempts

@auto_session
def set_user_failed_attempts(id: int, failed_attempts: int, session: Session = None) -> bool | None:
    """
    设置用户失败登录次数。

    参数:
        id (int): 用户ID。
        failed_attempts (int): 用户失败登录次数。

    返回:
        bool | None: 如果设置成功返回True，否则返回False；如果发生错误返回None。
    """
    user = session.get(User, id)
    if not user:
        return False
    user.failed_attempts = failed_attempts
    session.flush()
    return True